package hooks

import (
	"fmt"
	"gitee.com/youbeiwuhuan/gin-practice/gin-tonic/consts"
	"gitee.com/youbeiwuhuan/gin-practice/gin-tonic/render"
	"github.com/gin-gonic/gin"
	"github.com/juju/errors"
	"github.com/loopfz/gadgeto/tonic"
)

// RenderHook is the default render hook.
// It marshals the payload to JSON, or returns an empty body if the payload is nil.
// If Gin is running in debug mode, the marshalled JSON is indented.
func RenderHook(c *gin.Context, statusCode int, payload interface{}) {
	fmt.Printf("--------RenderHook,%d,%+v %T \n", statusCode, payload, payload)
	/**
	statusCode  是回应前端的http 状态码
	payload 是handler返回的参数
	*/
	var status int
	if c.Writer.Written() {
		status = c.Writer.Status()
	} else {
		status = statusCode
	}

	resp := render.OkResp(payload)
	// 没有返回值
	if payload == nil {
		renderJson(c, status, resp)
		return
	}

	// 返回error
	if e, ok := payload.(error); ok {
		status = 200
		if 400 == statusCode {
			resp = render.ValidErr(e.Error())
		} else {
			resp = render.ErrResp(e.Error(), nil)
		}
		renderJson(c, status, resp)
		return
	}

	// 返回参数就是RespData类型
	if d, ok := payload.(render.RespData); ok {
		resp = d
		renderJson(c, status, resp)
		return
	}
	// 非render.RespData则返回包装
	renderJson(c, status, resp)
}

func renderJson(c *gin.Context, status int, resp render.RespData) {
	if gin.IsDebugging() {
		c.IndentedJSON(status, resp)
	} else {
		c.JSON(status, resp)
	}
}

func ErrHook(c *gin.Context, e error) (int, interface{}) {

	errcode := 500
	if _, ok := e.(tonic.BindError); ok {
		errcode = 400
	} else {
		switch {
		case errors.IsBadRequest(e) || errors.IsNotValid(e) || errors.IsAlreadyExists(e) || errors.IsNotSupported(e) || errors.IsNotAssigned(e) || errors.IsNotProvisioned(e):
			errcode = 400
		case errors.IsForbidden(e):
			errcode = 403
		case errors.IsMethodNotAllowed(e):
			errcode = 405
		case errors.IsNotFound(e) || errors.IsUserNotFound(e):
			errcode = 404
		case errors.IsUnauthorized(e):
			errcode = 401
		case errors.IsNotImplemented(e):
			errcode = 501
		}
	}

	return errcode, e
}

// DefaultExecHook is the default exec hook.
// It simply executes the wrapping gin-handler with
// the given context.
func ExecHook(c *gin.Context, h gin.HandlerFunc, fname string) {
	fmt.Printf("--------Handler  before,%s \n", fname)

	//在hadnder执行前获取登录用户id
	c.Set(consts.USER_ID, "1234556")
	h(c)
	// 在hander执行后打印日志
	fmt.Printf("--------Handler  after,%s \n", fname)
}
